
#ifndef __EDNN_DEF_H__
#define __EDNN_DEF_H__



#include "ednn_config.h"



/**
 * @addtogroup Basic @{
 */
#define _EDNN_VERSION           1L
#define _EDNN_SUBVERSION        0L
#define _EDNN_REVISION          0L

#define EDNN_VERSION            ((_EDNN_VERSION * 10000) + \
                                         (_EDNN_SUBVERSION * 100) + _EDNN_REVISION)

#define EDNN_NULL               (0)
#define EDNN_TRUE				(1)
#define EDNN_FALSE			    (0)

typedef unsigned long           ednn_size_t;
typedef unsigned char           ednn_bool_t;
typedef signed char             ednn_int8_t;
typedef signed short            ednn_int16_t;
typedef signed int              ednn_int32_t;
typedef signed long long        ednn_int64_t;       
typedef unsigned char           ednn_uint8_t;
typedef unsigned short          ednn_uint16_t;
typedef unsigned int            ednn_uint32_t;
typedef unsigned long long      ednn_uint64_t;

#define ednn_q7_t               ednn_int8_t
#define ednn_q15_t              ednn_int16_t
#define ednn_q31_t              ednn_int32_t
#define ednn_q63_t              ednn_int64_t
#define ednn_qfmt_parm_t        ednn_int32_t
#define ednn_shape_t            ednn_uint16_t

#define EDNN_ALIGN              (sizeof(int*))

typedef enum {
    ednn_ok = 0,
    ednn_err_common,
    ednn_err_param,
} ednn_ret;

struct ednn_list_node {
    struct ednn_list_node *next;
    struct ednn_list_node *prev;
};
typedef struct ednn_list_node ednn_list_t;

struct ednn_str_builder {
	char *p;
	char *head;
	int   max;
	int   len;
};
typedef struct ednn_str_builder ednn_strb_t;

struct ednn_loglevel
{
    const char *string;
    ednn_uint32_t level;
};

typedef enum 
{
    EDNN_LOG_NONE = 0,
    EDNN_LOG_DEBUG,
    EDNN_LOG_INFO,
    EDNN_LOG_NOTICE,
    EDNN_LOG_WARN,
    EDNN_LOG_ERR
} ednn_loglevel;
/* @} end of Basic */


/**
 * @addtogroup Model
 */
typedef enum 
{
    EDNN_LAYER_UNKNOWN = 0,
    
    EDNN_LAYER_INPUT,
    EDNN_LAYER_OUTPUT,

    EDNN_LAYER_CONV_2D,
    EDNN_LAYER_DW_CONV_2D,
    EDNN_LAYER_CONV2D_TRANS,

    EDNN_LAYER_RNN,

    EDNN_LAYER_BATCHNORM,

    EDNN_LAYER_ZERO_PADDING,

    EDNN_LAYER_ACTIVATION,
    EDNN_LAYER_RELU,
    EDNN_LAYER_LEAKY_RELU,
    EDNN_LAYER_ADV_RELU,
    EDNN_LAYER_SIGMOID,
    EDNN_LAYER_TANH,
    EDNN_LAYER_SOFTMAX,

    EDNN_LAYER_MAXPOOL,
    EDNN_LAYER_GLOBAL_MAXPOOL,
    EDNN_LAYER_AVGPOOL,
    EDNN_LAYER_GLOBAL_AVGPOOL,
    EDNN_LAYER_SUMPOOL,
    EDNN_LAYER_GLOBAL_SUMPOOL,
    
    EDNN_LAYER_UPSAMPLE,
    EDNN_LAYER_DENSE,
    EDNN_LAYER_FLATTEN,
    EDNN_LAYER_RESHAPE,
    EDNN_LAYER_LAMBDA,
    EDNN_LAYER_CONCAT,
    EDNN_LAYER_ADD,
    EDNN_LAYER_SUB,
    EDNN_LAYER_MULT,

    EDNN_LAYER_OFFSET,
} ednn_layer_type;

#define EDNN_LAYER_NAMES    \
    {                       \
        "Unknown",          \
        "Input",            \
        "Output",           \
        "Conv2D",           \
        "DWConv2D",         \
        "Conv2DTrsp",       \
        "RNN",              \
        "BatchNorm",        \
        "ZeroPad",          \
        "Activation",       \
        "ReLU",             \
        "LeakyReLU",        \
        "AdvReLU",          \
        "Sigmoid",          \
        "Tanh",             \
        "Softmax",          \
        "MaxPool",          \
        "GMaxPool",         \
        "AvgPool",          \
        "GAvgPool",         \
        "SumPool",          \
        "GSumPool",         \
        "UpSample",         \
        "Dense",            \
        "Flatten",          \
        "Reshape",          \
        "Lambda",           \
        "Concat",           \
        "Add",              \
        "Sub",              \
        "Mult",             \
    }
extern const char ednn_layer_names[][CONFIG_EDNN_NAME_MAX];

typedef enum {
    EDNN_ACT_UNKNOWN = 0,
    EDNN_ACT_RELU,
    EDNN_ACT_LEAKY_RELU,
    EDNN_ACT_ADV_RELU,
    EDNN_ACT_TANH,
    EDNN_ACT_SIGMOID,
    EDNN_ACT_HARD_TANH,
    EDNN_ACT_HARD_SIGMOID
} ednn_activation_type;

#define EDNN_ACTIVATION_NAMES   \
	{                           \
        "Unknown",              \
		"ReLU",                 \
		"LkyReLU",		        \
		"AdvReLU",		        \
		"TanH",                 \
		"Sigmoid",              \
        "HTanH",                \
		"HSigd",                \
	}
extern const char ednn_activation_names[][CONFIG_EDNN_NAME_MAX];

typedef enum
{
    EDNN_UNKNOWN_PADDING = 0,
    EDNN_SAME_PADDING,
    EDNN_ZERO_PADDING,
} ednn_padding_type;

typedef enum
{
	EDNN_QTYPE_TENSOR = 0,
	EDNN_QTYPE_AXIS = 1
} ednn_qtype_t;

struct ednn_shape3d {
    ednn_shape_t h, w, c;
};
typedef struct ednn_shape3d ednn_shape3d_t;

struct ednn_tensor
{
    void          *pd;

    ednn_uint16_t *dim;
    ednn_uint8_t   ndim;

    ednn_uint8_t   bitwidth;       /* data's bitwidth, 8bit or 16bit */
};

struct ednn_activation
{
    ednn_activation_type type;

    struct ednn_tensor *tensor;

    /* activation function's running method */
    ednn_ret (*run)(struct ednn_activation *act);
};
typedef struct ednn_activation ednn_activation_t;

struct ednn_layer_stat
{
    ednn_uint32_t params;
    ednn_uint32_t ops;
    ednn_uint32_t mem;
};

struct ednn_layer
{
    ednn_layer_type        type;

    struct ednn_activation activation;

    struct ednn_tensor    *output;

    struct ednn_memblock  *output_mem;

    ednn_size_t            comp_size;
    struct ednn_memblock  *comp_mem;

    ednn_uint8_t           has_computational_buf:1;
    ednn_uint8_t           flags_reserve:7;

    struct ednn_layer_stat stat;

    ednn_ret (*forward)(struct ednn_layer *layer);

    /* when model do compile, it will call auto */
    ednn_ret (*build)(struct ednn_layer *layer);

    ednn_list_t list;
};
typedef struct ednn_layer ednn_layer_t;

struct ednn_memblock 
{
    void        *p;
    ednn_size_t  size;
    ednn_uint8_t owners;
    ednn_uint8_t state;
};
typedef struct ednn_memblock ednn_memblock_t;

struct ednn_model
{
    char name[CONFIG_EDNN_NAME_MAX];

    ednn_list_t layers;
    ednn_uint32_t layers_nr;

    ednn_ret (*layer_callback)(struct ednn_model *model, 
        struct ednn_layer *layer);
    
    struct ednn_memblock memblocks[CONFIG_EDNN_MEMBLOCK_NUM];

    ednn_uint32_t total_params;

    ednn_uint32_t is_structured:1;
    ednn_uint32_t is_parameterized:1;
    ednn_uint32_t is_compiled:1;
    ednn_uint32_t flags_reserve:29;
};
typedef struct ednn_model ednn_model_t;
/* @} end of Model */

#endif /* __EDNN_DEF_H__ */